package com.minelx.statementsplus.cha.core;

import com.minelx.statementsplus.cha.common.Node;
import com.minelx.util.multithread.ITask;
import com.minelx.util.multithread.IWorker;
import com.minelx.util.multithread.IWorking;

import java.util.List;

import static java.util.stream.Collectors.toList;

public class TreeTaskWorker<E> implements AutoCloseable {

	private final IWorker mainTaskWorker;

	private final IWorker leafTaskWorker;

	private final IWorker subTaskWorker;

	public TreeTaskWorker(int leafWorkingCount) {
		mainTaskWorker = IWorker.size(1);
		leafTaskWorker = IWorker.size(leafWorkingCount);
		subTaskWorker = IWorker.size(1);
	}

	public IWorking submitTask(Node<E> task, INodeTaskFactory<E> nodeTaskFactory) {
		// build task tree
		return mainTaskWorker.work(new NodeTask(task, nodeTaskFactory));
	}

	@Override
	public void close() {
		subTaskWorker.close();
		leafTaskWorker.close();
		mainTaskWorker.close();
	}

	private class NodeTask implements ITask {
		private final Node<E> task;

		private final INodeTaskFactory<E> nodeTaskFactory;

		public NodeTask(Node<E> task, INodeTaskFactory<E> nodeTaskFactory) {
			this.task = task;
			this.nodeTaskFactory = nodeTaskFactory;
		}

		@Override
		public void execute() {
			System.out.println("run all leaf tasks");
			// run all leaf tasks
			List<IWorking> leafWorkings = task.leaves().stream()
					.map(nodeTaskFactory::leafTask)
					.map(leafTaskWorker::work)
					.collect(toList());

			System.out.println("wait til them completed");
			// wait til them completed
			leafWorkings.forEach(this::waitForCompletion);

			System.out.println("merging downloaded files...");
			// merge sub tasks

			// FIXME 2021/8/7  wait for me!!!      sync it
			List<IWorking> subWorkings = task.subs()
					.map(nodeTaskFactory::subTask)
					.map(subTaskWorker::work)
					.collect(toList());
			subWorkings.forEach(this::waitForCompletion);
		}

		private void waitForCompletion(IWorking each) {
			try {
				each.waitForCompletion();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}

		@Override
		public long progress() {
			return 0;
		}
	}
}
